package com.wn.common.aop;

import com.wn.common.result.Code;
import com.wn.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * @program: projwe9
 * @description: 全局controller日志及异常打印
 * @author: Jason-Wei
 * @create: 2021-01-07 16:29
 **/

@Component
@Aspect
@Slf4j
public class ExceptionAspectHandler {

    @Autowired
    Result result;

    //这里 execution的配置很坑爹，需要注意“.”的数目所代表的含义
    @Pointcut("execution(* com.wn.*.controller..*.*(..))")
    public void pointCut() {

    }

    /**
     * @Description:  环绕通知，用于记录controller包中的方法调用及耗时，同时拦截异常
     * @Author: jason-wei
     * @Date: 2020-09-23 17:08:09
     * @param pjp
     * @return: java.lang.Object
     **/
    @Around("pointCut()")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) {
        StopWatch stopwatch = StopWatch.createStarted();

        try {
            log.warn("执行Controller开始:  方法路径--> " + pjp.getSignature() + " ，方法参数：" + Arrays.asList(pjp.getArgs()).toString());
            result = (Result) pjp.proceed(pjp.getArgs());
            log.warn("执行Controller结束: 方法路径--> " + pjp.getSignature() + "， 方法返回值：" + result.toString());
            stopwatch.stop();
            log.warn("耗时：" + stopwatch.getTime(TimeUnit.MILLISECONDS) + "(毫秒).");
        } catch (Throwable throwable) {
            result = handlerException(pjp, throwable);
        }

        return result;
    }

    /**
     * @Description: 处理拦截方法抛出的异常
     * @Author: jason-wei
     * @Date: 2020-09-23 17:09:56
     * @param pjp
     * @param e
     * @return: com.wn.common.result.Result
     **/
    private Result handlerException(ProceedingJoinPoint pjp, Throwable e) {

        if (e.getClass().isAssignableFrom(MyException.class)) {
            MyException myException = (MyException) e;
            log.error("RuntimeException  { 方法：" + pjp.getSignature() + "， 参数：" + Arrays.toString(pjp.getArgs()) + ",异常：" + myException.getException().getMessage() + "}", e);
            result = myException.getResult();
        } else if (e instanceof RuntimeException) {
            log.error("RuntimeException  { 方法：" + pjp.getSignature() + "， 参数：" + Arrays.toString(pjp.getArgs()) + ",异常：" + e.getMessage() + "}", e);
            result = new Result(Code.FAIL.getCode(), e.getMessage(), null);
        } else {
            log.error("异常 { 方法：" + pjp.getSignature() + "， 参数：" + Arrays.toString(pjp.getArgs()) + ",异常：" + e.getMessage() + "}", e);
            result = new Result(Code.FAIL.getCode(), e.getMessage(), null);
        }

        return result;
    }


}
